package com.stylefeng.guns.core.intercept;

import com.stylefeng.guns.core.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.core.util.IpUtil;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DefenseAjaxAttackFilter implements Filter {


    private final static String SQL_INJ_REG = "(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|"
            + "(\\b(select|update|union|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)";

    protected static Logger log = LogManager.getLogger(DefenseAjaxAttackFilter.class.getName());
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        String weburi = req.getRequestURI();
        try {
            if(!isExistIp(req)){
                resp.setCharacterEncoding("UTF-8");
                resp.setContentType("text/html;charset=UTF-8");
                resp.getWriter().println("非法IP访问!");
                return ;
            }

            Map<String, String[]> params = new HashMap<String, String[]>(req.getParameterMap());
            Set<String> keys = params.keySet();
            String tempComper = "";
            String[] values = null;
            boolean isErrorSql = false;
            //过滤菜单修改与新增时的路径
            if(!weburi.contains("/menu/add") &&  !weburi.contains("/menu/edit")){
                for (String key : keys) {
                    values = params.get(key);
                    if (null != values) {
                        for (int i = 0; i < values.length; i++) {

                            if (null != values[i] && !"".equalsIgnoreCase(values[i])) {
                                tempComper = values[i].replaceAll(SQL_INJ_REG,"");
                                if (!values[i].equalsIgnoreCase(tempComper)) {
                                    values[i] = tempComper;
                                    isErrorSql = true;
                                    log.warn("警告:用户" + req.getRemoteUser() + "IP:" + req.getRemoteAddr() + ". 尝试参数" + key + "SQL注入未成功!");
                                }
                            }
                        }
                        params.put(key, values);
                    } else {
                        params.put(key, new String[]{""});
                    }
                }
            }

            if (isErrorSql) {
                //重要：  此方法为重写方法
                ParameterRequestWrapper wrapRequest = new ParameterRequestWrapper(req, params);
                servletRequest = wrapRequest;
                filterChain.doFilter(servletRequest, resp);
            } else {
                filterChain.doFilter(servletRequest, resp);
            }

        } catch (Exception e) {
            e.printStackTrace();
            resp.sendRedirect("/login");
            return;
        }
    }

    @Override
    public void destroy() {

    }
    /**
     * 描述:是否是白名单
     * 创建人: xiang
     * 日期: 2018/8/4
     * 时间: 10:28
     */
    public  boolean isExistIp(HttpServletRequest request){
        String[] urlIp = IpUtil.getIpAddr(request).split(",");
        if(internalIp(urlIp[0].trim())){
            return true;
        }
        boolean isip=ConstantFactory.me().getIpaddressIp(urlIp[0].trim());
        if(!isip){
            log.warn("用户"+request.getRemoteUser()+"IP:"+urlIp[0].trim()+"未成功进入后台管理!");
        }
        return isip;
    }
    /**
     * 描述:校验是否是内网ip
     * 创建人: xiang
     * 日期: 2018/8/13
     * 时间: 21:42
     */
    public static boolean internalIp(String ip) {
        //匹配172.16.0.0 - 172.31.255.255的网段
        //String pattern_172 = "172\\.([1][6-9]|[2]\\d|3[01])(\\.([2][0-4]\\d|[2][5][0-5]|[01]?\\d?\\d)){2}";
        //匹配192.168.0.0 - 192.168.255.255的网段
        String pattern_192 = "192\\.168(\\.([2][0-4]\\d|[2][5][0-5]|[01]?\\d?\\d)){2}";
        Pattern reg = Pattern.compile(pattern_192);
        Matcher match = reg.matcher(ip);

        return match.find();
    }


}
